import * as THREE from 'three';

import { Material } from 'three';

import GLTFLoader from 'three-gltf-loader';

export default class FlySkyPlay {
    private camera: any;
    private scene: any;
    private renderer: any;
    private stats: any;
    private near: number = 1;
    private far: number = 2000;
    private clock: any;
    private controls: any;

    private moveForward: any = false;
    private moveBackward: any = false;
    private moveLeft: any = false;
    private moveRight: any = false;
    private canJump: any = false;
    private jumpHeight: number = 350;
    private movedistance: number = 100;

    private object: any;
    private texture: any;

    constructor(element: any) {
        this.init(element);
        this.AddControl(element);
        this.animate();
    }

    public LoadObjModel(path: string) {

        const manager = new THREE.LoadingManager(this.loadModel);
        manager.onProgress = (item, loaded, total) => {
            console.log(item, loaded, total);
        };

        // texture
        const textureLoader = new THREE.TextureLoader(manager);
        const texture = textureLoader.load('textures/UV_Grid_Sm.jpg');

        const loader = new THREEOBJLoader(manager);
        loader.load(path, (obj) => {
            this.object = obj;
            this.scene.add(this.object);
        }, this.onProgress, this.onError);
    }

    public LoadModelGltf(url: string) {
        // model
        const loader = new GLTFLoader();
        loader.load(
            url,
            (gltf) => {
                console.log(gltf);
            },
            (xhr) => {
                // called while loading is progressing
                console.log(`${(xhr.loaded / xhr.total * 100)}% loaded`);
            },
            (error) => {
                // called when loading has errors
                console.error('An error happened', error);
            },
        );

    }


    private loadModel() {
        if (this.object) {
            this.object.traverse((child) => {
                if (child.isMesh) {
                    child.material.map = this.texture;
                }
            });
            this.object.position.y = - 95;
            this.scene.add(this.object);
        }
    }

    private onProgress(xhr) {
        if (xhr.lengthComputable) {
            const percentComplete = xhr.loaded / xhr.total * 100;
            console.log('model ' + Math.round(percentComplete) + '% downloaded');
        }
    }
    private onError() {
        console.error('load error');
    }

    private init(element: any) {

        this.clock = new THREE.Clock();

        this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, this.near, this.far);
        this.camera.position.z = -10;
        this.camera.position.y = 2;
        this.scene = new THREE.Scene();

        //
        this.renderer = new THREE.WebGLRenderer({ alpha: true });
        this.renderer.setPixelRatio(window.devicePixelRatio);
        this.renderer.setSize(window.innerWidth, window.innerHeight);

        this.renderer.gammaInput = true;
        this.renderer.gammaOutput = true;

        this.Addbackground();

        this.addGround();


        element.appendChild(this.renderer.domElement);
        //
        this.stats = new Stats();

        element.appendChild(this.stats.dom);
        //
        window.addEventListener('resize', this.onWindowResize, false);

        this.renderer.render(this.scene, this.camera);

    }

    private Addbackground() {
        const urls = ['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'];
        this.scene.background = new THREE.CubeTextureLoader()
            .setPath('../sky/carsky/').load(
                urls,
            );
    }

    private onWindowResize = () => {
        this.camera.aspect = window.innerWidth / window.innerHeight;
        this.camera.updateProjectionMatrix();
        this.renderer.setSize(window.innerWidth, window.innerHeight);
    }
    private animate = () => {
        requestAnimationFrame(this.animate);
        this.render();
        this.stats.update();
    }
    private render = () => {
        const delta = this.clock.getDelta();

        // Fly update
        this.controls.update(delta);

        this.renderer.render(this.scene, this.camera);
    }

    private AddControl(container) {
        // const controls = new OrbitControls(this.camera);

        // controls.damping = 0.2;
        // controls.minPolarAngle = 1;
        // controls.minDistance = this.near;
        // controls.maxDistance = this.far;

        // // controls.minAzimuthAngle = 80 * Math.PI / 180; // radians
        // // controls.maxAzimuthAngle =  -230 * Math.PI / 180; // radians
        // controls.target = new THREE.Vector3(0, 0, 0);
        // controls.enablePan = true;

        this.AddFlyControl(container);
    }

    private addGround() {
        // var ground = new THREE.Mesh(
        //     new THREE.PlaneBufferGeometry( 2400, 2400 ),
        //     new THREE.ShadowMaterial( { colorWrite:true, opacity: 0.15, depthWrite: false }
        //     ) );
        // ground.rotation.x = - Math.PI / 2;
        // ground.receiveShadow = true;
        // ground.renderOrder = 1;
        // this.scene.add( ground );

        // // GROUND
        // const groundGeo = new THREE.PlaneBufferGeometry(2400, 2400);
        // const groundMat = new THREE.MeshLambertMaterial({color: 0xffffff,opacity: 0.15});
        // groundMat.color.setHSL(0.095, 1, 0.75);
        // const ground = new THREE.Mesh(groundGeo, groundMat);
        // ground.rotation.x = -Math.PI / 2;
        // ground.receiveShadow = true;
        // this.scene.add(ground);

        const grid = new THREE.GridHelper(1000, 40, 0x000000, 0x000000);
        if (grid.material instanceof Material) {
            grid.material.opacity = 0.2;
            grid.material.depthWrite = false;
            grid.material.transparent = true;
        }
        this.scene.add(grid);
    }

    private AddFlyControl(container) {
        // Fly Controls
        this.controls = new FlyControls(this.camera);
        this.controls.movementSpeed = 100;
        this.controls.domElement = container;
        this.controls.rollSpeed = Math.PI / 6;
        this.controls.autoForward = false;
        this.controls.dragToLook = false;

    }



}
